
import Cesium from '../Ces/Cesium'
import WeUniform from '../Display/WeUniform'
import FluidPrimitive from './FluidPrimitive'

class FluidNeighbor {
  private weUniform: WeUniform
  private _W: FluidPrimitive
  private _S: FluidPrimitive
  private _E: FluidPrimitive
  private _N: FluidPrimitive

  private _W_Tex:any// Cesium.Textrue
  private _S_Tex:any// Cesium.Textrue
  private _E_Tex:any// Cesium.Textrue
  private _N_Tex:any// Cesium.Textrue

  private _W_CurrentWaterTex:any// Cesium.Textrue
  private _S_CurrentWaterTex:any// Cesium.Textrue
  private _E_CurrentWaterTex:any// Cesium.Textrue
  private _N_CurrentWaterTex:any// Cesium.Textrue

  private _W_LastWaterTex:any// Cesium.Textrue
  private _S_LastWaterTex:any// Cesium.Textrue
  private _E_LastWaterTex:any// Cesium.Textrue
  private _N_LastWaterTex:any// Cesium.Textrue

  private _W_TmpTex:any// Cesium.Textrue
  private _S_TmpTex:any// Cesium.Textrue
  private _E_TmpTex:any// Cesium.Textrue
  private _N_TmpTex:any// Cesium.Textrue

  defaultTexture:any// Cesium.Texture
  constructor() {
    const floatUniform = {
      hasW: 0.0,
      hasS: 0.0,
      hasE: 0.0,
      hasN: 0.0,
    }
    this.weUniform = new WeUniform({
      floatUniform,
      name: 'FluidNeighbor_Uniform'
    })
  }

  getSource() {
    return `
    precision highp float;
    uniform sampler2D currentWater,lastWater,terrainTex,tmp;
    uniform sampler2D W_TerrainTex,S_TerrainTex,E_TerrainTex,N_TerrainTex;
    uniform sampler2D W_CurrentWaterTex,S_CurrentWaterTex,E_CurrentWaterTex,N_CurrentWaterTex;
    uniform sampler2D W_LastWaterTex,S_LastWaterTex,E_LastWaterTex,N_LastWaterTex;
    uniform sampler2D W_TmpTex,S_TmpTex,E_TmpTex,N_TmpTex;
    ${this.weUniform.getSource(true)}

    vec4 textureTile(vec2 uv,sampler2D center,sampler2D w,sampler2D s,sampler2D e,sampler2D n){
      float gridSize = Weget_numLon();
      float dx = 1.0 / gridSize * 0.5;
      float dy = 1.0 / gridSize;
      bool hasW = Weget_hasW() > 0.0;
      bool hasS = Weget_hasS() > 0.0;
      bool hasE = Weget_hasE() > 0.0;
      bool hasN = Weget_hasN() > 0.0;

      if(!hasW && uv.x < 0.0){
        return vec4(0.0);
      }
      if(!hasE && uv.x > 1.0){
        return vec4(0.0);
      }

      if(!hasN && uv.y < 0.0){
        return vec4(0.0);
      }
      if(!hasS && uv.y > 1.0){
        return vec4(0.0);
      }

      float m = 0.0;
      vec4 color = vec4(0.0);

      if(hasW && uv.x < dx){
        vec2 st = uv;
        st.x = 1.0 - abs(uv.x);
        color += texture(w,st);
        m++;
      }
      else if(hasE && uv.x > 1.0){
        vec2 st = uv;
        st.x = abs(1.0 - uv.x);
        color += texture(e,st);
        m++;
      }

      if(hasN && uv.y < dy){
        vec2 st = uv;
        st.y = 1.0 - abs(uv.y);
        color += texture(n,st);
        // if(uv.y > 0.0) return vec4(0.0);
        m++;
      }
      else if(hasS && uv.y > 1.0){
        vec2 st = uv;
        st.y = abs(uv.y - 1.0);
        if(uv.y < 1.0) {
          st.y = 1.0 - uv.y;
        }
        color += texture(s,st);
        m++;
      }

      // if(hasS && uv.y < 0.5){
      //   return vec4(0.0);
      // }

      if(m == 0.0){
        return texture(center,uv);
      }

      return color / m;
    }

    float getTerrainHeight(vec2 uv){
      return textureTile(uv,terrainTex,
        W_TerrainTex,S_TerrainTex,E_TerrainTex,N_TerrainTex).r;
    }

    vec4 getCurrentWater(vec2 uv){
      return textureTile(uv,currentWater,
        W_CurrentWaterTex,S_CurrentWaterTex,E_CurrentWaterTex,N_CurrentWaterTex);
    }
    vec4 getLastWater(vec2 uv){
       return textureTile(uv,lastWater,
        W_LastWaterTex,S_LastWaterTex,E_LastWaterTex,N_LastWaterTex);
    }
    vec4 getTmp(vec2 uv){
       return textureTile(uv,tmp,
        W_TmpTex,S_TmpTex,E_TmpTex,N_TmpTex);
    }
    `
  }

  setupUniformMap(uniformMap) {
    this.weUniform.setupUniformMap(uniformMap)
    uniformMap.W_TerrainTex = () => this.W
    uniformMap.S_TerrainTex = () => this.S
    uniformMap.E_TerrainTex = () => this.E
    uniformMap.N_TerrainTex = () => this.N

    uniformMap.W_CurrentWaterTex = () => this.W_CurrentWaterTex
    uniformMap.S_CurrentWaterTex = () => this.S_CurrentWaterTex
    uniformMap.E_CurrentWaterTex = () => this.E_CurrentWaterTex
    uniformMap.N_CurrentWaterTex = () => this.N_CurrentWaterTex

    uniformMap.W_LastWaterTex = () => this.W_LastWaterTex
    uniformMap.S_LastWaterTex = () => this.S_LastWaterTex
    uniformMap.E_LastWaterTex = () => this.E_LastWaterTex
    uniformMap.N_LastWaterTex = () => this.N_LastWaterTex


    uniformMap.W_TmpTex = () => this.W_TmpTex
    uniformMap.S_TmpTex = () => this.S_TmpTex
    uniformMap.E_TmpTex = () => this.E_TmpTex
    uniformMap.N_TmpTex = () => this.N_TmpTex
  }

  set W(value) {
    this._W = value
  }

  get W() {
    if (!this._W_Tex) {
      this._W_Tex = this._W?.terrainTexture
      if (this._W_Tex) {
        this._W_Tex.refCount++
        this.weUniform.Properties.hasW = 1.0
      }
    }
    return this._W_Tex || this.defaultTexture
  }

  get W_CurrentWaterTex() {
    if (!this._W_CurrentWaterTex) {
      this._W_CurrentWaterTex = this._W?.currentWater
      if (this._W_CurrentWaterTex) {
        this._W_CurrentWaterTex.refCount++
        this.weUniform.Properties.hasW = 1.0
      }
    }
    return this._W_CurrentWaterTex || this.defaultTexture
  }

  get W_LastWaterTex() {
    if (!this._W_LastWaterTex) {
      this._W_LastWaterTex = this._W?.lastWater
      if (this._W_LastWaterTex) {
        this._W_LastWaterTex.refCount++
        this.weUniform.Properties.hasW = 1.0
      }
    }
    return this._W_LastWaterTex || this.defaultTexture
  }

  get W_TmpTex() {
    if (!this._W_TmpTex) {
      this._W_TmpTex = this._W?.tmp
      if (this._W_TmpTex) {
        this._W_TmpTex.refCount++
        this.weUniform.Properties.hasW = 1.0
      }
    }
    return this._W_TmpTex || this.defaultTexture
  }

  set S(value) {
    this._S = value
  }

  get S() {
    if (!this._S_Tex) {
      this._S_Tex = this._S?.terrainTexture
      if (this._S_Tex) {
        this._S_Tex.refCount++
        this.weUniform.Properties.hasS = 1.0
      }
    }
    return this._S_Tex || this.defaultTexture
  }

  get S_CurrentWaterTex() {
    if (!this._S_CurrentWaterTex) {
      this._S_CurrentWaterTex = this._S?.currentWater
      if (this._S_CurrentWaterTex) {
        this._S_CurrentWaterTex.refCount++
        this.weUniform.Properties.hasS = 1.0
      }
    }
    return this._S_CurrentWaterTex || this.defaultTexture
  }

  get S_LastWaterTex() {
    if (!this._S_LastWaterTex) {
      this._S_LastWaterTex = this._S?.lastWater
      if (this._S_LastWaterTex) {
        this._S_LastWaterTex.refCount++
        this.weUniform.Properties.hasS = 1.0
      }
    }
    return this._S_LastWaterTex || this.defaultTexture
  }

  get S_TmpTex() {
    if (!this._S_TmpTex) {
      this._S_TmpTex = this._S?.tmp
      if (this._S_TmpTex) {
        this._S_TmpTex.refCount++
      }
    }
    return this._S_TmpTex || this.defaultTexture
  }

  set E(value) {
    this._E = value
  }

  get E() {
    if (!this._E_Tex) {
      this._E_Tex = this._E?.terrainTexture
      if (this._E_Tex) {
        this._E_Tex.refCount++
        this.weUniform.Properties.hasE = 1.0
      }
    }
    return this._E_Tex || this.defaultTexture
  }

  get E_CurrentWaterTex() {
    if (!this._E_CurrentWaterTex) {
      this._E_CurrentWaterTex = this._E?.currentWater
      if (this._E_CurrentWaterTex) {
        this._E_CurrentWaterTex.refCount++
        this.weUniform.Properties.hasE = 1.0
      }
    }
    return this._E_CurrentWaterTex || this.defaultTexture
  }

  get E_LastWaterTex() {
    if (!this._E_LastWaterTex) {
      this._E_LastWaterTex = this._E?.lastWater
      if (this._E_LastWaterTex) {
        this._E_LastWaterTex.refCount++
        this.weUniform.Properties.hasE = 1.0
      }
    }
    return this._E_LastWaterTex || this.defaultTexture
  }

  get E_TmpTex() {
    if (!this._E_TmpTex) {
      this._E_TmpTex = this._E?.tmp
      if (this._E_TmpTex) {
        this._E_TmpTex.refCount++
      }
    }
    return this._E_TmpTex || this.defaultTexture
  }

  set N(value) {
    this._N = value
  }

  get N() {
    if (!this._N_Tex) {
      this._N_Tex = this._N?.terrainTexture
      if (this._N_Tex) {
        this._N_Tex.refCount++
        this.weUniform.Properties.hasN = 1.0
      }
    }
    return this._N_Tex || this.defaultTexture
  }

  get N_CurrentWaterTex() {
    if (!this._N_CurrentWaterTex) {
      this._N_CurrentWaterTex = this._N?.currentWater
      if (this._N_CurrentWaterTex) {
        this._N_CurrentWaterTex.refCount++
        this.weUniform.Properties.hasN = 1.0
      }
    }
    return this._N_CurrentWaterTex || this.defaultTexture
  }

  get N_LastWaterTex() {
    if (!this._N_LastWaterTex) {
      this._N_LastWaterTex = this._N?.lastWater
      if (this._N_LastWaterTex) {
        this._N_LastWaterTex.refCount++
        this.weUniform.Properties.hasN = 1.0
      }
    }
    return this._N_LastWaterTex || this.defaultTexture
  }

  get N_TmpTex() {
    if (!this._N_TmpTex) {
      this._N_TmpTex = this._N?.tmp
      if (this._N_TmpTex) {
        this._N_TmpTex.refCount++
      }
    }
    return this._N_TmpTex || this.defaultTexture
  }

  isDestroyed() {
    return false
  }

  destroy() {
    this._W_Tex = this._W_Tex && this._W_Tex.destroy()
    this._S_Tex = this._S_Tex && this._S_Tex.destroy()
    this._E_Tex = this._E_Tex && this._E_Tex.destroy()
    this._N_Tex = this._N_Tex && this._N_Tex.destroy()


    this._W_CurrentWaterTex = this._W_CurrentWaterTex && this._W_CurrentWaterTex.destroy()
    this._S_CurrentWaterTex = this._S_CurrentWaterTex && this._S_CurrentWaterTex.destroy()
    this._E_CurrentWaterTex = this._E_CurrentWaterTex && this._E_CurrentWaterTex.destroy()
    this._N_CurrentWaterTex = this._N_CurrentWaterTex && this._N_CurrentWaterTex.destroy()


    this._W_LastWaterTex = this._W_LastWaterTex && this._W_LastWaterTex.destroy()
    this._S_LastWaterTex = this._S_LastWaterTex && this._S_LastWaterTex.destroy()
    this._E_LastWaterTex = this._E_LastWaterTex && this._E_LastWaterTex.destroy()
    this._N_LastWaterTex = this._N_LastWaterTex && this._N_LastWaterTex.destroy()

    this._W_TmpTex = this._W_TmpTex && this._W_TmpTex.destroy()
    this._S_TmpTex = this._S_TmpTex && this._S_TmpTex.destroy()
    this._E_TmpTex = this._E_TmpTex && this._E_TmpTex.destroy()
    this._N_TmpTex = this._N_TmpTex && this._N_TmpTex.destroy()

    return Cesium.destroyObject(this)
  }
}

export default FluidNeighbor
